package net.solarvistas.android;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Button;
import android.widget.ScrollView;
import android.view.View;
import android.view.KeyEvent;
import android.content.SharedPreferences;

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.io.*;

public class typroid extends Activity
{
    EditText cv;
    TextView tv;
    ScrollView sv;
    
    String cmd = "";
    String result = "";
    String cache = "";
    String workspace = "";

    final int KEY_RTN = 66;
    final int FOCUS_DOWN = 130;
    final String cache_path = "/data/data/net.solarvistas.android/files/";
    final String cache_file = "typroid.py";
    final String typroid_bin = "/system/bin/typroid";
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button btn = (Button) findViewById(R.id.clear);
        btn.setOnClickListener(new View.OnClickListener() {
        		public void onClick(View v) {
                    cache = ""; cmd = "";
                    isReturn(KEY_RTN);
                    result = evalPython();
                    tv.setText(result);
                }});
        btn = (Button) findViewById(R.id.save);
        btn.setOnClickListener(new View.OnClickListener() {
        		public void onClick(View v) {	cache = ""; }
        		});
        btn = (Button) findViewById(R.id.load);
        btn.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {	cache = ""; }
                });
                
        tv = new TextView(this);
        cv = (EditText)findViewById(R.id.command);
        cv.setLines(1);
        sv = (ScrollView)findViewById(R.id.result);
        sv.addView(tv);
        cv.setOnKeyListener(new View.OnKeyListener() {
            public boolean onKey(View v, int key, KeyEvent event) {
                cmd = cv.getText().toString();
                if(isReturn(key))
                    refresh();
                return false;
            } } );
        refresh();
    }

    public boolean isReturn(int key){
        tv.setText(result.substring(0,result.length()-1)+cmd);
        if(key == KEY_RTN){
            cache += cmd;cmd = "";
            save(cache_file);
            cv.setText(cmd);
            return true;
        }
        return false;
    }
    
    public String evalPython() {
        return exec(typroid_bin, cache_path+cache_file, null);
    }

    public void refresh(){
        result = evalPython();
        tv.setText(result);
    }

    @Override
    protected void onPause() {
        super.onPause();
        save(cache_file);
        SharedPreferences.Editor editor = getPreferences(0).edit();
        editor.putString("cmd", cv.getText().toString());
        editor.commit();
    }

    @Override
    protected void onResume() {
        super.onResume();
        load(cache_file);
        SharedPreferences prefs = getPreferences(0);
        String restoredText = prefs.getString("cmd", null);
        if (restoredText != null) {
            cv.setText(restoredText, TextView.BufferType.EDITABLE);
            cmd = restoredText;
        }
        refresh();
        isReturn(0);
    }

    private boolean load(String file_name) {
        try {
            InputStream is = new BufferedInputStream(openFileInput(file_name));
            DataInputStream in = new DataInputStream(is);
            String buf = in.readLine();
            cache = "";
            while(buf!=null){
                cache = cache + buf + "\n";
                buf = in.readLine();
            }
            in.close();
        } catch (FileNotFoundException e) {
            result = "[Error] I/O exception. Code: 0x01";
            return false;
        } catch (IOException e) {
            result = "[Error] I/O exception. Code: 0x02";
            return false;
        }
        return true;
    }

    private boolean save(String file_name) {
        try {
            OutputStream os = new BufferedOutputStream(openFileOutput(file_name,0));
            DataOutputStream out = new DataOutputStream(os);
            out.writeBytes(cache);
            out.close();
        } catch (IOException e) {
            result = "[Error] I/O exception. Code: 0x03";
            return false;
        }
        return true;
    }
    
    public String exec(String cmd, String arg1, String arg2){
        try {
            // android.os.Exec is not included in android.jar so we need to use reflection.
            Class<?> execClass = Class.forName("android.os.Exec");
            Method createSubprocess = execClass.getMethod("createSubprocess",
                                                    String.class, String.class, String.class, int[].class);
            Method waitFor = execClass.getMethod("waitFor", int.class);

            // Executes the command.
            // NOTE: createSubprocess() is asynchronous.
            int[] pid = new int[1];
            FileDescriptor fd = (FileDescriptor)createSubprocess.invoke(null, cmd, arg1, arg2, pid);

            // Reads stdout.
            // NOTE: You can write to stdin of the command using new FileOutputStream(fd).
            FileInputStream in = new FileInputStream(fd);
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String output = "";
            try {
                String line;
                while ((line = reader.readLine()) != null) {
                    output += line + "\n";
            }
            } catch (IOException e) {
                // It seems IOException is thrown when it reaches EOF.
            }

            // Waits for the command to finish.
            waitFor.invoke(null, pid[0]);
            return output;
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e.getMessage());
        } catch (SecurityException e) {
            throw new RuntimeException(e.getMessage());
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e.getMessage());
        } catch (IllegalArgumentException e) {
            throw new RuntimeException(e.getMessage());
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e.getMessage());
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}
